﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_OCF_Parser.h".
//-------------------------------------------------------------------

#include "MetaData.h"

namespace UX_STL
{
namespace UXMetaTypes
{
	
	static CMetaClass	_s_cGlobalNamespace;


	template <typename T, typename B>
	struct _TypeCast
	{
		static T & cast(T &dst, const B &src)
		{
			return ( dst = static_cast<T>(src) );
		}
	};


	template <typename B>
	struct _TypeCast<bool, B>
	{
		static bool & cast(bool &dst, const B &src)
		{
			return ( dst = IsNotZero(src) );
		}
	};


	template <typename T, typename B>
	inline T & type_cast(T &dst, const B &src)
	{
		return _TypeCast<T,B>::cast( dst, src );
	}


	
//-------------------------- IMetaBaseType ------------------------//
/*
=================================================
	конструктор
=================================================
*/
	IMetaBaseType::IMetaBaseType(uni_c_string pName, uint uOffset, usize uSize, e_value::type eType):
		_sName(pName), _uOffset(uOffset), _uSize(uSize), _eType(eType)
	{
	}
		
	bool IMetaBaseType::SetValue(void *pObj, const void * const pValue, e_value::type eType) const
	{
		return false;
	}

	bool IMetaBaseType::GetValue(void *pObj, void * pValue, e_value::type eType) const
	{
		return false;
	}
	bool IMetaBaseType::GetValue(void *pObj, string &sValue) const
	{
		return false;
	}

	bool IMetaBaseType::AddField(const void *pObj, const void *pField, uni_c_string pName, e_value::type eType)
	{
		return false;
	}

	bool IMetaBaseType::GetField(uni_c_string sName, IMetaBaseType *&pField) const
	{
		return false;
	}

	bool IMetaBaseType::GetField(uint uNumb, IMetaBaseType *&pField)
	{
		return false;
	}



// -------------------------- CMetaDefType ----------------------- //
/*
=================================================
	конструктор
=================================================
*/
	template <typename T, e_value::type E>
	CMetaDefType<T,E>::CMetaDefType(uni_c_string pName, uint uOffset):
		IMetaBaseType( pName, uOffset, sizeof(T), E )
	{
	}
	
	template <typename T, e_value::type E>
	CMetaDefType<T,E>::CMetaDefType(const CMetaDefType &cObj):
		IMetaBaseType( cObj._sName.cstr(), cObj._uOffset, cObj._uSize, E )
	{
	}
	
/*
=================================================
	деструктор
=================================================
*/
	template <typename T, e_value::type E>
	CMetaDefType<T,E>::~CMetaDefType()
	{
	}
	
/*
=================================================
	установить значение
=================================================
*/
	template <typename T, e_value::type E>
	inline void CMetaDefType<T,E>::_SetValue(void *pObj, T tValue) const
	{
		*MovePointer< T >( pObj, _uOffset ) = tValue;
	}
	
/*
=================================================
	сичитывает значение из объекта
=================================================
*/
	template <typename T, e_value::type E>
	inline void CMetaDefType<T,E>::_GetValue(void *pObj, T &tValue) const
	{
		tValue = *MovePointer< T >( pObj, _uOffset );
	}

/*
=================================================
	установить значение
=================================================
*/
	template <typename T, e_value::type E>
	bool CMetaDefType<T,E>::SetValue(void *pObj, const void * const pValue, e_value::type eType) const
	{
		T	temp;
		
		if ( !CMetaUtils::ConvertValue<T,E>( pValue, eType, temp ) )
			return false;

		_SetValue( pObj, temp );
		return true;
	}
	
/*
=================================================
	возвращает значение
=================================================
*/
	template <typename T, e_value::type E>
	bool CMetaDefType<T,E>::GetValue(void *pObj, void * pValue, e_value::type eType) const
	{
		T	temp;

		_GetValue( pObj, temp );
		return CMetaUtils::ConvertValue<T,E>( temp, eType, pValue );
	}
	
/*
=================================================
	возвращает значение
=================================================
*/
	template <typename T, e_value::type E>
	bool CMetaDefType<T,E>::GetValue(void *pObj, string &sValue) const
	{
		T	temp;

		_GetValue( pObj, temp );

		sValue << temp;
		return true;
	}



// ------------------------ CMetaStringType ---------------------- //
/*
=================================================
	конструктор
=================================================
*/
	CMetaStringType::CMetaStringType(uni_c_string pName, uint uOffset):
		IMetaBaseType( pName, uOffset, sizeof(string), e_value::STRING )
	{
	}
	
	CMetaStringType::CMetaStringType(const CMetaStringType &cObj):
		IMetaBaseType( cObj._sName.cstr(), cObj._uOffset, cObj._uSize, e_value::STRING )
	{
	}

/*
=================================================
	деструктор
=================================================
*/
	CMetaStringType::~CMetaStringType()
	{
	}

/*
=================================================
	копировать строку
=================================================
*/
	inline bool CMetaStringType::SetValue(void *pObj, const void * const pValue, e_value::type eType) const
	{
		switch ( eType )
		{
			case e_value::BOOL		:	*PointerCast< string >( ((uint8 *)pObj + _uOffset) ) = *(bool *)pValue;		break;
			case e_value::INT8		:	*PointerCast< string >( ((uint8 *)pObj + _uOffset) ) = *(int8 *)pValue;		break;
			case e_value::INT16		:	*PointerCast< string >( ((uint8 *)pObj + _uOffset) ) = *(int16 *)pValue;	break;
			case e_value::INT32		:	*PointerCast< string >( ((uint8 *)pObj + _uOffset) ) = *(int32 *)pValue;	break;
			case e_value::INT64		:	*PointerCast< string >( ((uint8 *)pObj + _uOffset) ) = *(int64 *)pValue;	break;
			case e_value::FLOAT		:	*PointerCast< string >( ((uint8 *)pObj + _uOffset) ) = *(float *)pValue;	break;
			case e_value::DOUBLE	:	*PointerCast< string >( ((uint8 *)pObj + _uOffset) ) = *(double *)pValue;	break;
			case e_value::STRING	:	*PointerCast< string >( ((uint8 *)pObj + _uOffset) ) = (const char *)pValue;break;
			default					:	return false;
		}
		return true;
	}
	
/*
=================================================
	возвращает значение
=================================================
*/
	inline bool CMetaStringType::GetValue(void *pObj, void * pValue, e_value::type eType) const
	{
		if ( eType != e_value::STRING )
			return false;

		*PointerCast< string >( pValue ) = *PointerCast< string >( ((uint8 *)pObj + _uOffset) );
		return true;
	}
	
/*
=================================================
	возвращает строку
=================================================
*/
	inline bool CMetaStringType::GetValue(void *pObj, string &sValue) const
	{
		sValue = *MovePointer< string >( pObj, _uOffset );
		return true;
	}

	

//-------------------------- CMetaArrayType -----------------------//
/*
=================================================
	конструктор
=================================================
*/
	CMetaArrayType::CMetaArrayType(const CMetaArrayType &cObj):
		IMetaBaseType( cObj._sName.cstr(), cObj._uOffset, cObj._uSize, e_value::ARRAY ),
		_uElemSize(cObj._uElemSize), _pResizeProc(cObj._pResizeProc)
	{
		CMetaUtils::CopyObject( cObj._pElemType, _pElemType );
	}

	CMetaArrayType::CMetaArrayType(uni_c_string pName, uint uOffset, uint uSize, IMetaBaseType *pType):
		IMetaBaseType( pName, uOffset, uSize, e_value::ARRAY ),
		_pElemType(pType), _uElemSize(0)
	{
		if ( pType != null )
			_uElemSize = pType->GetSize();
	}

/*
=================================================
	деструктор
=================================================
*/
	CMetaArrayType::~CMetaArrayType()
	{
		if ( _pElemType != null )
			CMetaUtils::Free( (IMetaBaseType *&)_pElemType );
	}
	
/*
=================================================
	устанавливает функцию для работы с массивом
=================================================
*/
	bool CMetaArrayType::SetProcs(PResizeProc_t pResize)
	{
		if ( pResize == null )
			return false;

		_pResizeProc = pResize;
		return true;
	}
	
/*
=================================================
	возвращает итератор массива
=================================================
*/
	bool CMetaArrayType::GetIterator(CMetaArrayIterator *&pIter, void *pObj)
	{
		if ( pObj == null or _pElemType == null )
			return false;

		pIter = new CMetaArrayIterator( this, (int8*)pObj + _uOffset );
		return true;
	}

	

//------------------------- CMetaVarArrayType ---------------------//
/*
=================================================
	конструктор
=================================================
*/
	CMetaVarArrayType::CMetaVarArrayType(const CMetaVarArrayType &cObj):
		IMetaBaseType( cObj._sName.cstr(), cObj._uOffset, cObj._uSize, e_value::VAR_ARRAY )
	{
	}

	CMetaVarArrayType::CMetaVarArrayType(uni_c_string pName, uint uOffset):
		IMetaBaseType( pName, uOffset, sizeof(variant_array_t), e_value::VAR_ARRAY )
	{
	}

/*
=================================================
	деструктор
=================================================
*/
	CMetaVarArrayType::~CMetaVarArrayType()
	{
	}
	
/*
=================================================
	возвращает итератор массива
=================================================
*/
	bool CMetaVarArrayType::GetIterator(CMetaVarArrayIterator *&pIter, void *pObj)
	{
		if ( pObj == null )
			return false;

		pIter = new CMetaVarArrayIterator( this, (int8*)pObj + _uOffset );
		return true;
	}



// ------------------------- CMetaStructType --------------------- //
/*
=================================================
	конструктор
=================================================
*/
	CMetaStructType::CMetaStructType(const CMetaStructType &cObj):
		IMetaBaseType( cObj._sName.cstr(), cObj._uOffset, cObj._uSize, e_value::BIN_ARRAY ),
		_pResizeProc(cObj._pResizeProc), _uAlign(cObj._uAlign)
	{
	}

	CMetaStructType::CMetaStructType(uni_c_string pName, uint uOffset):
		IMetaBaseType( pName, uOffset, sizeof(uint8_array_t), e_value::BIN_ARRAY ),
		_pResizeProc(null), _uAlign(sizeof(int32))
	{
	}

/*
=================================================
	деструктор
=================================================
*/
	CMetaStructType::~CMetaStructType()
	{
	}

/*
=================================================
	устанавливает функцию для работы с массивом
=================================================
*/
	bool CMetaStructType::SetProcs(PResizeProc_t pResize)
	{
		if ( pResize == null )
			return false;

		_pResizeProc = pResize;
		return true;
	}

/*
=================================================
	возвращает итератор структуры
=================================================
*/
	bool CMetaStructType::GetIterator(CMetaStructIterator *&pIter, void *pObj)
	{
		if ( pObj == null )
			return false;

		pIter = new CMetaStructIterator( this, (int8*)pObj + _uOffset );
		return true;
	}

	

// --------------------------- IMetaObject ----------------------- //
/*
=================================================
	
=================================================
*/
	inline void GetNamespaces(const string &sIdent, uni_c_string_array_t &aNamespaces)
	{
		const char *	p_word = sIdent.cstr();

		usize	i = 0;
		for (; i < sIdent.Length(); ++i)
		{
			if ( sIdent[i] != '.' )
				continue;

			aNamespaces.PushBack( uni_c_string( p_word, PointerOffset( &sIdent[i], p_word ) ) );
			p_word = &sIdent[i+1];
		}
		aNamespaces.PushBack( uni_c_string( p_word, PointerOffset( &sIdent[i], p_word ) ) );
	}

/*
=================================================
	конструктор
=================================================
*/
	IMetaObject::IMetaObject(string &sName)
	{
		_sTypeName.SetString( sName );
		GetNamespaces( _sTypeName, _sNamespaces );
	}

	IMetaObject::IMetaObject(uni_c_string pName):
		_sTypeName(pName)
	{
		GetNamespaces( _sTypeName, _sNamespaces );
	}



// --------------------------- CMetaObject ----------------------- //
/*
=================================================
	конструктор
=================================================
*/
	CMetaObject::CMetaObject(CMetaObject *pNS, uni_c_string pName, uint uSize):
		IMetaObject(pName), _pNamespace(pNS), _uSize(uSize),
		_pCreateObjectProc(null), _pCreateArrayProc(null), _pParameter(null)
	{
		if ( _pNamespace != null )
			_pNamespace->AddToNamespace( this );
	}
		
	CMetaObject::CMetaObject(CMetaObject *pNS, string &sName, uint uSize):
		IMetaObject(sName), _pNamespace(pNS), _uSize(uSize),
		_pCreateObjectProc(null), _pCreateArrayProc(null), _pParameter(null)
	{
		if ( _pNamespace != null )
			_pNamespace->AddToNamespace( this );
	}

	CMetaObject::CMetaObject(const CMetaObject &cObj, uni_c_string pName, uint uSize):
		IMetaObject(pName), _pNamespace(cObj._pNamespace), _uSize(uSize), _aTypes(cObj._aTypes),
		_pCreateObjectProc( cObj._pCreateObjectProc ), _pCreateArrayProc( cObj._pCreateArrayProc ),
		_pParameter( cObj._pParameter )
	{
		if ( _uSize == 0 )
			_uSize = cObj._uSize;

		_CopyFields( cObj );
		
		if ( _pNamespace != null )
			_pNamespace->AddToNamespace( this );
	}

/*
=================================================
	деструктор
=================================================
*/
	CMetaObject::~CMetaObject()
	{
		if ( _pNamespace != null )
			_pNamespace->RemoveFromNamespace( this );

		FOR( i, _aFields ) {
			delete _aFields[i];
		}
		_aFields.Clear();
	}
	
/*
=================================================
	добавить тип в пространство имен
=================================================
*/
	void CMetaObject::AddToNamespace(IMetaObject *pType)
	{
		ASSUME( pType != null );
		_aTypes.PushBack( pType );
	}
	
/*
=================================================
	удалить тип из пространства имен
=================================================
*/
	void CMetaObject::RemoveFromNamespace(IMetaObject *pType)
	{
		FOR( i, _aTypes ) {
			if ( _aTypes[i] == pType ) {
				_aTypes.Erase( i );
				return;
			}
		}
		WARNING( "can't find meta object in this namespace" );
	}

/*
=================================================
	ищет поле объекта по имени
=================================================
*/
	bool CMetaObject::GetField(uni_c_string sName, IMetaBaseType *&pField) const
	{
		FOR( i, _aFields )
		{
			if ( _aFields[i]->GetName() == sName )
			{
				pField = _aFields[i];
				return true;
			}
		}
		return false;
	}
	
/*
=================================================
	ищет поле объекта по номеру
=================================================
*/
	bool CMetaObject::GetField(uint uNumb, IMetaBaseType *&pField)
	{
		if ( uNumb >= _aFields.Count() )
			return false;

		pField = _aFields[uNumb];
		return true;
	}
	
/*
=================================================
	ищет объект внутри объекта и
	во вложенных объектах
=================================================
*/
	bool CMetaObject::GetObj(uni_c_string sName, IMetaBaseType *&pObj, uint &uOffset) const
	{
		uni_c_string_array_t	a_obj_names;
		usize					u_size		= 0,
								i			= 0;

		for (i = 0; i < sName.Length(); ++i)
		{
			if ( sName[i] == '.' )
			{
				a_obj_names.PushBack( uni_c_string( sName.cstr() + u_size, i-u_size ) );
				u_size = i+1;
			}
		}
		a_obj_names.PushBack( uni_c_string( sName.cstr() + u_size, i-u_size ) );

		IMetaBaseType	*p_obj	= new CMetaObjectType( null, 0, (CMetaObject *)this ),
						*temp	= p_obj;

		u_size = 0;

		for (i = 0; i < a_obj_names.Count(); ++i)
		{
			if ( !temp->GetField( a_obj_names[i], temp ) ) {
				delete p_obj;
				return false;
			}

			u_size += temp->GetOffset();
		}
		
		delete p_obj;

		pObj	 = temp;
		uOffset	+= u_size;

		return true;
	}

/*
=================================================
	копирует поля объекта
=================================================
*/
	bool CMetaObject::_CopyFields(const CMetaObject &cObj)
	{
		if ( cObj._aFields.Empty() )
			return false;

		_aFields.Resize( cObj._aFields.Count() );

		FOR( i, cObj._aFields )
		{
			CMetaUtils::CopyObject( cObj._aFields[i], _aFields[i] );
		}
		return true;
	}
	
/*
=================================================
	создает объект
=================================================
*/
	bool CMetaObject::CreateObject(CMetaSetIterator *&pIter, TVariant &sVar)
	{
		if ( _pCreateObjectProc == null )
			return false;
		return _pCreateObjectProc( pIter, sVar, _pParameter );
	}
	
/*
=================================================
	создает массив объектов
=================================================
*/
	bool CMetaObject::CreateObjectArray(CMetaArrayIterator *&pIter, TVariant &sVar)
	{
		if ( _pCreateArrayProc == null )
			return false;
		return _pCreateArrayProc( pIter, sVar, _pParameter );
	}



// ------------------------ CMetaObjectType ---------------------- //
/*
=================================================
	конструктор
=================================================
*/
	CMetaObjectType::CMetaObjectType(const CMetaObjectType &cObj):
		IMetaBaseType( cObj._sName.cstr(), cObj._uOffset, cObj._uSize, e_value::OBJECT ),
		_pType(cObj._pType)
	{
	}

	CMetaObjectType::CMetaObjectType(uni_c_string pName, uint uOffset, CMetaObject *pObj):
		IMetaBaseType( pName, uOffset, pObj->GetSize(), e_value::OBJECT ),
		_pType(pObj)
	{
	}

/*
=================================================
	деструктор
=================================================
*/
	CMetaObjectType::~CMetaObjectType()
	{
	}
	
/*
=================================================
	возвращает указатель на поле объекта
=================================================
*/
	bool CMetaObjectType::GetField(uni_c_string sName, IMetaBaseType *&pField) const
	{
		FOR( i, _pType->_aFields )
		{
			if ( _pType->_aFields[i]->GetName() == sName ) {
				pField = _pType->_aFields[i];
				return true;
			}
		}
		return false;
	}

/*
=================================================
	возвращает указатель на поле объекта
=================================================
*/
	bool CMetaObjectType::GetField(uint uNumb, IMetaBaseType *&pField)
	{
		if ( uNumb >= _pType->_aFields.Count() )
			return false;

		pField = _pType->_aFields[uNumb];
		return true;
	}


// ------------------------ CMetaCustomType ---------------------- //
/*
=================================================
	конструктор
=================================================
*/
	CMetaCustomType::CMetaCustomType(const CMetaCustomType &cObj):
		IMetaBaseType( cObj._sName.cstr(), cObj._uOffset, cObj._uSize, e_value::CUSTOM ),
		_pObj(cObj._pObj)
	{
	}

	CMetaCustomType::CMetaCustomType(uni_c_string pName, uint uOffset, uint uSize):
		IMetaBaseType( pName, uOffset, uSize, e_value::CUSTOM ),
		_pObj(null)
	{
	}

/*
=================================================
	деструктор
=================================================
*/
	CMetaCustomType::~CMetaCustomType()
	{
	}

/*
=================================================
	установить значение
=================================================
*/
	bool CMetaCustomType::SetValue(void *pObj, const void * const pValue, e_value::type eType) const
	{
		return ( _pObj != null and _pObj->SetValue( pObj, pValue, eType ) );
	}

/*
=================================================
	передает функцию установки значения
=================================================
*/
	bool CMetaCustomType::SetProc(IMetaCustomObject *pObj)
	{
		_pObj = pObj;
		return true;
	}
	
/*
=================================================
	возвращает значение
=================================================
*/
	bool CMetaCustomType::GetValue(void *pObj, void * pValue, e_value::type eType) const
	{
		ASSUME( _pObj != null );
		return ( _pObj != null and _pObj->GetValue( pObj, pValue, eType ) );
	}

/*
=================================================
	возвращает строковое значение
=================================================
*/
	bool CMetaCustomType::GetValue(void *pObj, string &sValue) const
	{
		ASSUME( _pObj != null );
		return ( _pObj != null and _pObj->GetValue( pObj, sValue ) );
	}
	
/*
=================================================
	возвращает поле по имени
=================================================
*/
	bool CMetaCustomType::GetField(uni_c_string sName, IMetaBaseType *&pField) const
	{
		ASSUME( _pObj != null );
		return ( _pObj != null and _pObj->GetField( sName, pField ) );
	}
	
/*
=================================================
	возвращает поле по номеру
=================================================
*/
	bool CMetaCustomType::GetField(uint uNumb, IMetaBaseType *&pField)
	{
		ASSUME( _pObj != null );
		return ( _pObj != null and _pObj->GetField( uNumb, pField ) );
	}

	

// -------------------------- CMetaUtils ------------------------- //
/*
=================================================
	возвращает копию класса
=================================================
*/
	inline bool CMetaUtils::CopyObject(IMetaBaseType *pObj, IMetaBaseType *&pNewObj)
	{
		pNewObj = null;

		if ( pObj == null ) {
			WARNING( "object for copy is Null!" );
			return false;
		}

		switch ( pObj->GetType() )
		{
			case e_value::BOOL		:	pNewObj = new CMetaBoolType  ( *((CMetaBoolType	  *)pObj) );	break;
			case e_value::INT8		:	pNewObj = new CMetaInt8Type  ( *((CMetaInt8Type	  *)pObj) );	break;
			case e_value::INT16		:	pNewObj = new CMetaInt16Type ( *((CMetaInt16Type  *)pObj) );	break;
			case e_value::INT32		:	pNewObj = new CMetaInt32Type ( *((CMetaInt32Type  *)pObj) );	break;
			case e_value::INT64		:	pNewObj = new CMetaInt64Type ( *((CMetaInt64Type  *)pObj) );	break;
			case e_value::FLOAT		:	pNewObj = new CMetaFloatType ( *((CMetaFloatType  *)pObj) );	break;
			case e_value::DOUBLE	:	pNewObj = new CMetaDoubleType( *((CMetaDoubleType *)pObj) );	break;
			case e_value::STRING	:	pNewObj = new CMetaStringType( *((CMetaStringType *)pObj) );	break;
			case e_value::OBJECT	:	pNewObj = new CMetaObjectType( *((CMetaObjectType *)pObj) );	break;
			case e_value::ARRAY		:	pNewObj = new CMetaArrayType ( *((CMetaArrayType  *)pObj) );	break;
			case e_value::CUSTOM	:	pNewObj = new CMetaCustomType( *((CMetaCustomType *)pObj) );	break;
			case e_value::VAR_ARRAY :	pNewObj = new CMetaVarArrayType( *((CMetaVarArrayType *)pObj) );break;
			default					:	WARNING( "unsupported type for copy field operation!" );  return false;
		}
		return true;
	}
	
/*
=================================================
	конвертация типов
=================================================
*/
	template <typename T, e_value::type E>
	inline bool CMetaUtils::ConvertValue(const void * const pValue, e_value::type eType, T &tRes)
	{
		if ( eType == E ) {
			tRes = *(T*)pValue;
			return true;
		}

		switch ( eType )
		{
			case e_value::BOOL		:	type_cast( tRes, *((bool   *)pValue) );	break;
			case e_value::INT8		:	type_cast( tRes, *((int8   *)pValue) );	break;
			case e_value::INT16		:	type_cast( tRes, *((int16  *)pValue) );	break;
			case e_value::INT32		:	type_cast( tRes, *((int32  *)pValue) );	break;
			case e_value::INT64		:	type_cast( tRes, *((int64  *)pValue) );	break;
			case e_value::FLOAT		:	type_cast( tRes, *((float  *)pValue) );	break;
			case e_value::DOUBLE	:	type_cast( tRes, *((double *)pValue) );	break;
			default					:	WARNING( "unsupported value type for conversion!" );  return false;
		};
		return true;
	}
	
/*
=================================================
	конвертация типов
=================================================
*/
	template <typename T, e_value::type E>
	inline bool CMetaUtils::ConvertValue(const T &tValue, e_value::type eType, void *pRes)
	{
		if ( eType == E ) {
			*(T*)pRes = tValue;
			return true;
		}

		switch ( eType )
		{
			case e_value::BOOL		:	type_cast( *(bool   *)pRes, tValue );	break;
			case e_value::INT8		:	type_cast( *(int8   *)pRes, tValue );	break;
			case e_value::INT16		:	type_cast( *(int16  *)pRes, tValue );	break;
			case e_value::INT32		:	type_cast( *(int32  *)pRes, tValue );	break;
			case e_value::INT64		:	type_cast( *(int64  *)pRes, tValue );	break;
			case e_value::FLOAT		:	type_cast( *(float  *)pRes, tValue );	break;
			case e_value::DOUBLE	:	type_cast( *(double *)pRes, tValue );	break;
			default					:	WARNING( "unsupported value type for conversion!" );  return false;
		};
		return true;
	}

/*
=================================================
	удаляет объект
=================================================
*/
	inline void CMetaUtils::Free(IMetaBaseType *&pObj)
	{
		delete pObj;
		pObj = null;
	}
	
/*
=================================================
	найти объект
=================================================
*/
	bool CMetaUtils::_FindObject(uni_c_string sTypeName, CMetaObject *&pObj)
	{
		CMetaObject *	p_ns = _s_cGlobalNamespace.GetObjectType();
		
		uni_c_string_array_t	a_obj_names;
		usize					u_size		= 0,
								i			= 0;

		for (i = 0; i < sTypeName.Length(); ++i)
		{
			if ( sTypeName[i] == '.' )
			{
				a_obj_names.PushBack( uni_c_string( sTypeName.cstr() + u_size, i-u_size ) );
				u_size = i+1;
			}
		}
		a_obj_names.PushBack( uni_c_string( sTypeName.cstr() + u_size, i-u_size ) );


		FOR( j, a_obj_names )
		{
			const CMetaObject::metaobj_array_t &	a_types = p_ns->_aTypes;
			bool									b_found	= false;

			FOR( l, a_types )
			{
				if ( a_types[l]->GetFullTypeName().Back() == a_obj_names[j] )
				{
					if ( !a_types[l]->IsObject() )
						continue;

					b_found = true;
					p_ns	= a_types[l].ToPtr< CMetaObject >();
					break;
				}
			}
			
			if ( !b_found )
				return false;
		}

		pObj = p_ns;
		return true;
	}
	
/*
=================================================
	создает объект
=================================================
*/
	bool CMetaUtils::Create(uni_c_string sTypeName, CMetaSetIterator *&pIter, TVariant &sVar)
	{
		CMetaObject *	p_obj = null;
		return _FindObject( sTypeName, p_obj ) and p_obj->CreateObject( pIter, sVar );
	}
	
/*
=================================================
	создает массив объектов
=================================================
*/
	template <typename T>
	bool CALLBACK s_CreateStdArray(CMetaArrayIterator *&pIter, TVariant &sVar, void *)
	{
		sVar = T();
		IMetaBaseType *	p_arr = CreateMetaObject( null, 0, sizeof(T), sVar.Get<T>() );
		if ( p_arr == null )
			return false;

		pIter = new CMetaArrayIterator( (CMetaArrayType *)p_arr, sVar.GetPtr() );
		return true;
	}


	bool CMetaUtils::CreateArray(uni_c_string sTypeName, CMetaArrayIterator *&pIter, TVariant &sVar)
	{
		struct TStandartType {
			uni_c_string			sName;
			PArrayConstructProc_t	pProc;
			///
			TStandartType(const char *name, PArrayConstructProc_t proc): sName(name), pProc(proc) {}
		};

		static const TStandartType	s_aStdTypes[] = {
			TStandartType( "bool",		&s_CreateStdArray< bool_array_t > ),
			TStandartType( "int8",		&s_CreateStdArray< int8_array_t > ),
			TStandartType( "uint8",		&s_CreateStdArray< uint8_array_t > ),
			TStandartType( "int16",		&s_CreateStdArray< int16_array_t > ),
			TStandartType( "uint16",	&s_CreateStdArray< uint16_array_t > ),
			TStandartType( "int32",		&s_CreateStdArray< int32_array_t > ),
			TStandartType( "uint32",	&s_CreateStdArray< uint32_array_t > ),
			TStandartType( "int64",		&s_CreateStdArray< int64_array_t > ),
			TStandartType( "uint64",	&s_CreateStdArray< uint64_array_t > ),
			TStandartType( "long",		&s_CreateStdArray< int64_array_t > ),
			TStandartType( "ulong",		&s_CreateStdArray< uint64_array_t > ),
			TStandartType( "float",		&s_CreateStdArray< float_array_t > ),
			TStandartType( "double",	&s_CreateStdArray< double_array_t > ),
			TStandartType( "int",		&s_CreateStdArray< int32_array_t > ),
			TStandartType( "uint",		&s_CreateStdArray< uint32_array_t > ),
			TStandartType( "isize",		&s_CreateStdArray< isize_array_t > ),
			TStandartType( "usize",		&s_CreateStdArray< usize_array_t > ),
			TStandartType( "float32",	&s_CreateStdArray< float_array_t > ),
			TStandartType( "float64",	&s_CreateStdArray< double_array_t > ),
			TStandartType( "string",	&s_CreateStdArray< string_array_t > ),
		};

		for (usize i = 0; i < CountOf( s_aStdTypes ); ++i)
		{
			if ( s_aStdTypes[i].sName == sTypeName )
				return s_aStdTypes[i].pProc( pIter, sVar, null );
		}

		CMetaObject *	p_obj = null;
		return _FindObject( sTypeName, p_obj ) and p_obj->CreateObjectArray( pIter, sVar );
	}
	
/*
=================================================
	добавить новое имя объекта
=================================================
*/
	bool CMetaUtils::Typedef(const CMetaClass &cObj, uni_c_string sNewTypeName, CMetaObject *pNS)
	{
		CMetaObject	*	p_namespace	= ( pNS != null ? pNS : _s_cGlobalNamespace.GetObjectType() );
		
		if ( !CMetaClass::_s_Compare( p_namespace, sNewTypeName ) )
			return false;

		p_namespace->_aTypes.PushBack( new CMetaTypedef( p_namespace, sNewTypeName.cstr(), cObj.GetObject()->GetObj() ) );
		return true;
	}



// -------------------------- CMetaClass ------------------------- //
/*
=================================================
	конструктор
=================================================
*/
	CMetaClass::CMetaClass(): _pObject(null), _bInit(false)
	{
	}

/*
=================================================
	деструктор
=================================================
*/
	CMetaClass::~CMetaClass()
	{
	}
	
/*
=================================================
	возвращает итераторы
=================================================
*/
	CMetaAddIterator * CMetaClass::_GetAddIter(const void *pObj) const
	{
		return new CMetaAddIterator( _pObject->GetObj(), pObj );
	}
	
	CMetaSetIterator * CMetaClass::_GetSetIter(const void *pObj) const
	{
		ASSUME( pObj != null );
		return new CMetaSetIterator( pObj, _pObject );
	}

/*
=================================================
	устанавливает функцию создания объекта
=================================================
*/
	void CMetaClass::SetConstructorProcs(PObjectConstructProc_t pObj, PArrayConstructProc_t pArr, void *pParam)
	{
		_pObject->GetObj()->SetConstructorProcs( pObj, pArr, pParam );
	}
	
/*
=================================================
	создать глобальное пространство имен
=================================================
*/
	void CMetaClass::_CreateGlobal()
	{
		static CMetaObject	s_cObj( null, "", 1 );

		_pObject = new CMetaObjectType( null, 0, &s_cObj );
	}

/*
=================================================
	создать новый объект
=================================================
*/
	bool CMetaClass::Create(uni_c_string pName, usize uSize, CMetaObject *pNamespace)
	{
		if ( pNamespace == null )
			pNamespace = _s_cGlobalNamespace.GetObjectType();

		if ( pName == null or _bInit or !_s_Compare( pNamespace, string(pName) ) )
			return false;

		string	s_name( pName );

		if ( pNamespace != null )
			pNamespace->GetTypeName() >> s_name;

		_pObject = new CMetaObjectType( null, 0, new CMetaObject( pNamespace, s_name, uSize ) );
		return (_bInit = _pObject != null);
	}
	
/*
=================================================
	добавить поля из другого класса
=================================================
*/
	bool CMetaClass::Inherit(const CMetaClass &cObj)
	{
		return _pObject->GetObj()->_CopyFields( *cObj.GetObject()->GetObj() );
	}
	
/*
=================================================
	добавить поля из другого класса
=================================================
*/
	bool CMetaClass::Inherit(uni_c_string sTypeName, CMetaObject *pNamespace)
	{
		const CMetaObject::metaobj_array_t &	a_types = pNamespace != null ?
															pNamespace->_aTypes :
															_s_cGlobalNamespace.GetObjectType()->_aTypes;

		FOR( i, a_types ) {
			if ( sTypeName == a_types[i]->GetFullTypeName().Back() ) {
				return _pObject->GetObj()->_CopyFields( *a_types[i]->GetMetaObject() );
			}
		}
		return false;
	}

/*
=================================================
	ищет имя среди созданных типов
=================================================
*/
	bool CMetaClass::_s_Compare(CMetaObject *pNamespace, const string &sName)
	{
		const CMetaObject::metaobj_array_t &	a_types = pNamespace != null ?
															pNamespace->_aTypes :
															_s_cGlobalNamespace.GetObjectType()->_aTypes;

		FOR( i, a_types ) {
			if ( sName == a_types[i]->GetFullTypeName().Back() ) {
				WARNING( "this name already in use" );
				return false;
			}
		}

		return true;
	}
	
/*
=================================================
	создает объект
=================================================
*/
	bool CMetaClass::CreateObject(CMetaSetIterator *&pIter, TVariant &sVar)
	{
		return _pObject->GetObj()->CreateObject( pIter, sVar );
	}
	
/*
=================================================
	создает массив объектов
=================================================
*/
	bool CMetaClass::CreateObjectArray(CMetaArrayIterator *&pIter, TVariant &sVar)
	{
		return _pObject->GetObj()->CreateObjectArray( pIter, sVar );
	}
	
/*
=================================================
	базовые типы
=================================================
*/
	static	CMetaClass		_cMetaPoint2f,
							_cMetaPoint2d,
							_cMetaPoint2i,
							_cMetaPoint3f,
							_cMetaPoint3d,
							_cMetaPoint3i,
							_cMetaPoint4f,
							_cMetaPoint4d,
							_cMetaPoint4i,
							_cMetaRectf,
							_cMetaRectd,
							_cMetaRecti,
							_cMetaColor4u,
							_cMetaQuaternionf,
							_cMetaQuaterniond;
							//_cMetaColor4f,
							//_cMetaTransformf,
							//_cMetaTransformd,
							//_cMetaExtTransformf,
							//_cMetaExtTransformd,
							//_cMetaDate;


/*
=================================================
	инициализация базовых типов
=================================================
*/
	bool CMetaClass::s_InitBaseTypes(CMetaObject *pNS)
	{
		//using namespace UXMathExt;

		if ( _cMetaPoint2f.IsInit() or _cMetaPoint2i.IsInit()	or _cMetaPoint2d.IsInit()	or
			 _cMetaPoint3f.IsInit() or _cMetaPoint3i.IsInit()	or _cMetaPoint3d.IsInit()	or
			 _cMetaPoint4f.IsInit()	or _cMetaPoint4i.IsInit()	or _cMetaPoint4d.IsInit()	or
			 _cMetaRectf.IsInit()	or _cMetaRecti.IsInit()		or _cMetaRectd.IsInit()		or
			 _cMetaColor4u.IsInit()	or _cMetaQuaternionf.IsInit() or _cMetaQuaterniond.IsInit()	or
			 //_cMetaColor4f.IsInit()	or 
			// _cMetaTransformf.IsInit()		or _cMetaTransformd.IsInit()	or
			// _cMetaExtTransformf.IsInit()	or _cMetaExtTransformd.IsInit() or
			 _s_cGlobalNamespace.IsInit() )
		{
			return false;
		}

		_s_cGlobalNamespace._CreateGlobal();

		fvec2			s_vec2;
		dvec2			s_dvec2;
		ivec2			s_ivec2;
		fvec3			s_vec3;
		dvec3			s_dvec3;
		ivec3			s_ivec3;
		fvec4			s_vec4;
		dvec4			s_dvec4;
		ivec4			s_ivec4;
		frect			s_rectf;
		drect			s_rectd;
		irect			s_recti;
		fquat			s_quaternionf;
		dquat			s_quaterniond;
		color4u			s_color4u;
		//transform_f		s_transformf;
		//transform_d		s_transformd;

		UX_CREATE_METACLASS_EXT( _cMetaPoint2f,		fvec2,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaPoint2d,		dvec2,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaPoint2i,		ivec2,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaPoint3f,		fvec3,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaPoint3d,		dvec3,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaPoint3i,		ivec3,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaPoint4f,		fvec4,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaPoint4d,		dvec4,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaPoint4i,		ivec4,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaRectf,		frect,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaRectd,		drect,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaRecti,		irect,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaQuaternionf,	fquat,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaQuaterniond,	dquat,		pNS );
		UX_CREATE_METACLASS_EXT( _cMetaColor4u,		color4u,	pNS );
		//UX_CREATE_METACLASS_EXT( _cMetaTransformf,	transform_t,pNS );
		//UX_CREATE_METACLASS_EXT( _cMetaTransformd,	transform_d,pNS );

		CMetaAddIteratorPtr	iter;

		iter = _cMetaPoint2f.GetAddIter( s_vec2 );
		iter->AddField( s_vec2.x,	"x"	);
		iter->AddField( s_vec2.y,	"y"	);

		iter = _cMetaPoint2d.GetAddIter( s_dvec2 );
		iter->AddField( s_dvec2.x,	"x" );
		iter->AddField( s_dvec2.y,	"y" );

		iter = _cMetaPoint2i.GetAddIter( s_ivec2 );
		iter->AddField( s_ivec2.x,	"x"	);
		iter->AddField( s_ivec2.y,	"y"	);

		CMetaUtils::Typedef( _cMetaPoint2i, "uvec2"	);

		iter = _cMetaPoint3f.GetAddIter( s_vec3 );
		iter->AddField( s_vec3.x,	"x"	);
		iter->AddField( s_vec3.y,	"y"	);
		iter->AddField( s_vec3.z,	"z"	);

		iter = _cMetaPoint3d.GetAddIter( s_dvec3 );
		iter->AddField( s_dvec3.x,	"x"	);
		iter->AddField( s_dvec3.y,	"y"	);
		iter->AddField(	s_dvec3.z,	"z"	);

		iter = _cMetaPoint3i.GetAddIter( s_ivec3 );
		iter->AddField( s_ivec3.x,	"x"	);
		iter->AddField( s_ivec3.y,	"y"	);
		iter->AddField( s_ivec3.z,	"z"	);

		CMetaUtils::Typedef( _cMetaPoint3i,	"uvec3"	);

		iter = _cMetaPoint4f.GetAddIter( s_vec4 );
		iter->AddField( s_vec4.x,	"x"	);
		iter->AddField( s_vec4.y,	"y"	);
		iter->AddField( s_vec4.z,	"z"	);
		iter->AddField( s_vec4.w,	"w"	);

		iter = _cMetaPoint4d.GetAddIter( s_dvec4 );
		iter->AddField( s_dvec4.x,	"x"	);
		iter->AddField( s_dvec4.y,	"y"	);
		iter->AddField( s_dvec4.z,	"z"	);
		iter->AddField( s_dvec4.w,	"w"	);

		iter = _cMetaPoint4i.GetAddIter( s_ivec4 );
		iter->AddField( s_ivec4.x,	"x"	);
		iter->AddField( s_ivec4.y,	"y"	);
		iter->AddField( s_ivec4.z,	"z"	);
		iter->AddField( s_ivec4.w,	"w"	);

		CMetaUtils::Typedef( _cMetaPoint4i,	"uvec4"	);

		iter = _cMetaRectf.GetAddIter( s_rectf );
		iter->AddField( s_rectf.left,	"left"	);
		iter->AddField( s_rectf.bottom,	"bottom");
		iter->AddField( s_rectf.right,	"right"	);
		iter->AddField( s_rectf.top,	"top"	);

		iter = _cMetaRectd.GetAddIter( s_rectd );
		iter->AddField( s_rectd.left,	"left"	);
		iter->AddField( s_rectd.bottom,	"bottom");
		iter->AddField( s_rectd.right,	"right"	);
		iter->AddField( s_rectd.top,	"top"	);

		iter = _cMetaRecti.GetAddIter( s_recti );
		iter->AddField( s_recti.left,	"left"	);
		iter->AddField( s_recti.bottom,	"bottom");
		iter->AddField( s_recti.right,	"right"	);
		iter->AddField( s_recti.top,	"top"	);

		CMetaUtils::Typedef( _cMetaRecti,	"urect"	);

		iter = _cMetaQuaternionf.GetAddIter( s_quaternionf );
		iter->AddField(	s_quaternionf.x,	"x"	);
		iter->AddField(	s_quaternionf.y,	"y"	);
		iter->AddField(	s_quaternionf.z,	"z"	);
		iter->AddField(	s_quaternionf.w,	"w"	);
		
		iter = _cMetaQuaterniond.GetAddIter( s_quaterniond );
		iter->AddField(	s_quaterniond.x,	"x"	);
		iter->AddField(	s_quaterniond.y,	"y"	);
		iter->AddField(	s_quaterniond.z,	"z"	);
		iter->AddField(	s_quaterniond.w,	"w"	);

		iter = _cMetaColor4u.GetAddIter( s_color4u );
		iter->AddField(	s_color4u.x,			"x"	);
		iter->AddField(	s_color4u.y,			"y"	);
		iter->AddField(	s_color4u.z,			"z"	);
		iter->AddField(	s_color4u.w,			"w"	);
		iter->AddField( s_color4u.x,			"r" );
		iter->AddField( s_color4u.y,			"g" );
		iter->AddField( s_color4u.z,			"b" );
		iter->AddField( s_color4u.w,			"a" );
		iter->AddField( s_color4u.ToIntRGBA(),	"rgba" );	// TODO: test this

		//iter = _cMetaTransformf.GetAddIter( s_transformf );
		//iter->AddField( s_transformf.Position(),	"position"		);
		//iter->AddField( s_transformf.Orientation(),	"orientation"	);
		
		//iter = _cMetaTransformd.GetAddIter( s_transformd );
		//iter->AddField( s_transformd.Position(),	"position"		);
		//iter->AddField( s_transformd.Orientation(),	"orientation"	);

		return true;
	}



//------------------------ CMetaArrayIterator ---------------------//
	
	CMetaArrayIterator::CMetaArrayIterator(CMetaArrayType *pMtArr, void *pObj):
		_pType(pMtArr), _pArr( static_cast<arrayDummy*>(pObj) ), _uNumb(0)
	{
	}

	CMetaArrayIterator::CMetaArrayIterator(const CMetaArrayIterator &iter):
		_pType(iter._pType), _pArr(iter._pArr), _uNumb(iter._uNumb)
	{
	}

	CMetaArrayIterator::~CMetaArrayIterator()
	{
	}

	void CMetaArrayIterator::Free()
	{
		delete this;
	}
	
	bool CMetaArrayIterator::GetSetIterator(CMetaSetIterator *&pIter) const
	{
		if ( _pType->_pElemType->GetType() != e_value::OBJECT )
			return false;

		pIter = new CMetaSetIterator( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, _pType->_pElemType.ToPtr< CMetaObjectType >() );
		return true;
	}
	
	bool CMetaArrayIterator::GetArrIterator(CMetaArrayIterator *&pIter)	const
	{
		if ( _pType->_pElemType->GetType() != e_value::ARRAY )
			return false;

		pIter = new CMetaArrayIterator( _pType->_pElemType.ToPtr< CMetaArrayType >(), (uint8*)_pArr->pMemory + _pType->_uElemSize * _uNumb );
		return true;
	}
	
	bool CMetaArrayIterator::GetStrIterator(CMetaStructIterator *&pIter) const
	{
		if ( _pType->_pElemType->GetType() != e_value::BIN_ARRAY )
			return false;

		pIter = new CMetaStructIterator( _pType->_pElemType.ToPtr< CMetaStructType >(), (uint8*)_pArr->pMemory + _pType->_uElemSize * _uNumb );
		return true;
	}
	
	bool CMetaArrayIterator::GetVarIterator(CMetaVarArrayIterator *&pIter) const
	{
		if ( _pType->_pElemType->GetType() != e_value::VAR_ARRAY )
			return false;

		pIter = new CMetaVarArrayIterator( _pType->_pElemType.ToPtr< CMetaVarArrayType >(), (uint8*)_pArr->pMemory + _pType->_uElemSize * _uNumb );
		return true;
	}



//----------------------- CMetaVarArrayIterator -------------------//
	
	CMetaVarArrayIterator::CMetaVarArrayIterator(CMetaVarArrayType *pMtArr, void *pObj):
		_pType(pMtArr), _pArr( static_cast<variant_array_t*>(pObj) ), _uNumb(0)
	{
	}

	CMetaVarArrayIterator::CMetaVarArrayIterator(const CMetaVarArrayIterator &iter):
		_pType(iter._pType), _pArr(iter._pArr), _uNumb(iter._uNumb)
	{
	}

	CMetaVarArrayIterator::~CMetaVarArrayIterator()
	{
		FOR( i, _aTypes ) {
			CMetaUtils::Free( _aTypes[i] );
		}
		_aTypes.Clear();
	}

	void CMetaVarArrayIterator::Free()
	{
		delete this;
	}
	
	bool CMetaVarArrayIterator::GetSetIterator(uni_c_string sTypeName, CMetaSetIterator *&pIter)
	{
		if ( !CMetaUtils::Create( sTypeName, pIter, (*_pArr)[_uNumb] ) )
			return false;

		_aTypes.PushBack( pIter->GetObjType() );
		return true;
	}
	
	bool CMetaVarArrayIterator::GetArrIterator(uni_c_string sTypeName, CMetaArrayIterator *&pIter)
	{
		if ( !CMetaUtils::CreateArray( sTypeName, pIter, (*_pArr)[_uNumb] ) )
			return false;

		_aTypes.PushBack( pIter->GetArrayType() );
		return true;
	}
	
	bool CMetaVarArrayIterator::GetStrIterator(CMetaStructIterator *&pIter)
	{
		(*_pArr)[_uNumb] = binary_array_t();

		CMetaStructType *	p_struct = new CMetaStructType( null, 0 );
		_aTypes.PushBack( p_struct );

		pIter = new CMetaStructIterator( p_struct, (*_pArr)[_uNumb].GetPtr() );
		return true;
	}
	
	bool CMetaVarArrayIterator::GetVarIterator(CMetaVarArrayIterator *&pIter)
	{
		(*_pArr)[_uNumb] = variant_array_t();

		CMetaVarArrayType *	p_var_arr = new CMetaVarArrayType( null, 0 );
		_aTypes.PushBack( p_var_arr );

		pIter = new CMetaVarArrayIterator( p_var_arr, (*_pArr)[_uNumb].GetPtr() );
		return true;
	}

	bool CMetaVarArrayIterator::SetValue(uni_c_string sName, const void *pData, e_value::type eType) const
	{
		return false;
	}

	bool CMetaVarArrayIterator::SetValue(const void *pData, e_value::type eType) const
	{
		switch ( eType )
		{
			case e_value::BOOL :	(*_pArr)[_uNumb] = *(bool *)pData;					break;
			case e_value::INT8 :	(*_pArr)[_uNumb] = *(int8 *)pData;					break;
			case e_value::INT16 :	(*_pArr)[_uNumb] = *(int16 *)pData;					break;
			case e_value::INT32 :	(*_pArr)[_uNumb] = *(int32 *)pData;					break;
			case e_value::INT64 :	(*_pArr)[_uNumb] = *(int64 *)pData;					break;
			case e_value::FLOAT :	(*_pArr)[_uNumb] = *(float *)pData;					break;
			case e_value::DOUBLE :	(*_pArr)[_uNumb] = *(double *)pData;				break;
			case e_value::STRING :	(*_pArr)[_uNumb] = string( (const char *)pData );	break;
			default :				return false;
		};
		return true;
	}
	


//----------------------- CMetaStructIterator ---------------------//
		
	CMetaStructIterator::CMetaStructIterator(CMetaStructType *pMtStr, void *pObj):
		_pType(pMtStr), _pArr( static_cast<arrayDummy*>(pObj) ), _uPos(0)
	{
	}

	CMetaStructIterator::CMetaStructIterator(const CMetaStructIterator &iter):
		_pType(iter._pType), _pArr(iter._pArr), _uPos(iter._uPos)
	{
	}

	CMetaStructIterator::~CMetaStructIterator()
	{
	}

	void CMetaStructIterator::Free()
	{
		delete this;
	}

	CMetaStructIterator & CMetaStructIterator::operator = (const CMetaStructIterator &right)
	{
		_pType	= right._pType;
		_pArr	= right._pArr;
		_uPos	= right._uPos;
		return *this;
	}

	bool CMetaStructIterator::PushBackValue(const void *pData, e_value::type eType)
	{
		uint8_array_t	&arr	= ReferenceCast< uint8_array_t >( *_pArr.ptr() );
		uint8			align	= _pType->GetAlign();

		arr.Resize( arr.Count() + align );

		void	*		value	= (uint8*)arr.End() - align;
		bool			ret		= false;
		
		// float
		if ( !ret and align == sizeof(float) )
		{
			if ( eType == e_value::FLOAT ){
				type_cast( *(float*)value, *(float*)pData );
				ret = true;
			}
			else
			if ( eType == e_value::DOUBLE ) {
				type_cast( *(float*)value, *(double*)pData );
				ret = true;
			}
		}
		
		// int32
		if ( !ret and align == sizeof(int32) )
		{
			ret = true;

			switch ( eType )
			{
				case e_value::BOOL		:	type_cast( *(int32*)value, *(bool*)pData );		break;
				case e_value::INT8		:	type_cast( *(int32*)value, *(int8*)pData );		break;
				case e_value::INT16		:	type_cast( *(int32*)value, *(int16*)pData );	break;
				case e_value::INT32		:	type_cast( *(int32*)value, *(int32*)pData );	break;
				case e_value::INT64		:	type_cast( *(int32*)value, *(int64*)pData );	break;
				default					:	ret = false;
			}
		}

		// double
		if ( !ret and align == sizeof(double) )
		{
			if ( eType == e_value::FLOAT ) {
				type_cast( *(double*)value, *(float*)pData );
				ret = true;
			}
			else
			if ( eType == e_value::DOUBLE ) {
				type_cast( *(double*)value, *(double*)pData );
				ret = true;
			}
		}

		// int64
		if ( !ret and align == sizeof(int64) )
		{
			ret = true;

			switch ( eType )
			{
				case e_value::BOOL		:	type_cast( *(int64*)value, *(bool*)pData );		break;
				case e_value::INT8		:	type_cast( *(int64*)value, *(int8*)pData );		break;
				case e_value::INT16		:	type_cast( *(int64*)value, *(int16*)pData );	break;
				case e_value::INT32		:	type_cast( *(int64*)value, *(int32*)pData );	break;
				case e_value::INT64		:	type_cast( *(int64*)value, *(int64*)pData );	break;
				default					:	ret = false;
			}
		}

		return ret;
	}


// ------------------------ CMetaSetIterator --------------------- //
	
	CMetaSetIterator::CMetaSetIterator(const void *pObj, CMetaObjectType *pBase):
		_pObj(pObj), _pBase(pBase), _pCurObj(pBase), _uOffset(0)
	{
	}

	CMetaSetIterator::CMetaSetIterator(const CMetaSetIterator &cIter, bool bIsObject):
		_pBase(cIter._pBase), _pCurObj(cIter._pCurObj), _pObj(cIter._pObj), _uOffset(cIter._uOffset)
	{
		if ( bIsObject and cIter._pCurObj->GetType() == e_value::OBJECT )
		{
			_pBase	 = cIter._pCurObj.ToPtr< CMetaObjectType >();
			_pObj	 = MovePointer( cIter._pObj, cIter._uOffset );
			_uOffset = 0;
		}
	}

	CMetaSetIterator::~CMetaSetIterator()
	{
	}
	
	void CMetaSetIterator::Free()
	{
		delete this;
	}
	

// ------------------------ CMetaAddIterator --------------------- //

	CMetaAddIterator::CMetaAddIterator()
	{}

	CMetaAddIterator::CMetaAddIterator(CMetaObject *pMObj, const void *pObj)
	{
		_sObjStack.Push( TMetaInfo( pMObj, pObj ) );
	}
	
	CMetaAddIterator::CMetaAddIterator(const CMetaAddIterator &cIter): _sObjStack( cIter._sObjStack )
	{
	}

	CMetaAddIterator::~CMetaAddIterator()
	{
	}

	void CMetaAddIterator::Free()
	{
		delete this;
	}
	
	void CMetaAddIterator::AddField(CMetaObject *pMetaObject, const void *pField, uni_c_string pName)
	{
		TMetaInfo	&	s_info	 = _sObjStack.Get();
		const usize		u_offset = PointerOffset( pField, s_info.pClObj );

		return s_info.pMtObj->AddField( new CMetaObjectType( pName, u_offset, pMetaObject /*cMetaClass.GetObjectType()*/ ) );
	}


	void CMetaAddIterator::AddField(CMetaObject *pElemMetaClass, const void *pArrayField, uni_c_string pName, PResizeProc_t pResizeProc, usize uFieldSize)
	{
		TMetaInfo	&	s_info	 = _sObjStack.Get();
		const usize		u_offset = PointerOffset( pArrayField, s_info.pClObj );

		return s_info.pMtObj->AddField(
					CreateMetaArray( pName, u_offset, pResizeProc, uFieldSize,
						new CMetaObjectType( null, 0, pElemMetaClass /*cElemMetaClass.GetObjectType()*/ ) ) ); 
	}
	
}	// UXMetaTypes

//-------------------------------------------------------------------
	
	UX_DECLARE_META_OBJECT( bool )					{ return new UXMetaTypes::CMetaBoolType( pName, uOffset ); }
	UX_DECLARE_META_OBJECT( int8 )					{ return new UXMetaTypes::CMetaInt8Type( pName, uOffset ); }
	UX_DECLARE_META_OBJECT( int16 )					{ return new UXMetaTypes::CMetaInt16Type( pName, uOffset ); }
	UX_DECLARE_META_OBJECT( int32 )					{ return new UXMetaTypes::CMetaInt32Type( pName, uOffset ); }
	UX_DECLARE_META_OBJECT( int64 )					{ return new UXMetaTypes::CMetaInt64Type( pName, uOffset ); }
	UX_DECLARE_META_OBJECT( float )					{ return new UXMetaTypes::CMetaFloatType( pName, uOffset ); }
	UX_DECLARE_META_OBJECT( double )				{ return new UXMetaTypes::CMetaDoubleType( pName, uOffset ); }
	UX_DECLARE_META_OBJECT( float32_t )				{ return new UXMetaTypes::CMetaFloatType( pName, uOffset ); }
	UX_DECLARE_META_OBJECT( float64_t )				{ return new UXMetaTypes::CMetaDoubleType( pName, uOffset ); }
	//UX_DECLARE_META_OBJECT( TVariant )			{ return new UXMetaTypes::CMetaVariantType( pName, uOffset ); }


	UX_DECLARE_META_OBJECT( UXMath::fvec2 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint2f.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::dvec2 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint2d.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::ivec2 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint2i.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::uvec2 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint2i.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::fvec3 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint3f.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::dvec3 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint3d.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::ivec3 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint3i.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::uvec3 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint3i.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::fvec4 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint4f.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::dvec4 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint4d.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::ivec4 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint4i.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::uvec4 )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaPoint4i.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::frect )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaRectf.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::drect )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaRectd.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::irect )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaRecti.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::urect )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaRecti.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::fquat )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaQuaternionf.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::dquat )			{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaQuaterniond.GetObject()->GetObj() ); }
	UX_DECLARE_META_OBJECT( UXMath::color4u )		{ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaColor4u.GetObject()->GetObj() ); }
	//UX_DECLARE_META_OBJECT( UXMathExt::transform_f ){ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaTransformf.GetObject()->GetObj() ); }
	//UX_DECLARE_META_OBJECT( UXMathExt::transform_d ){ return new UXMetaTypes::CMetaObjectType( pName, uOffset, UXMetaTypes::_cMetaTransformd.GetObject()->GetObj() ); }
	
	UX_DECLARE_META_OBJECT( string )
	{
		return new UXMetaTypes::CMetaStringType( pName, uOffset );
	}

	UX_DECLARE_META_OBJECT( binary_array_t )
	{
		UXMetaTypes::CMetaStructType	*	p_struct = new UXMetaTypes::CMetaStructType( pName, uOffset );
		p_struct->SetProcs( &binary_array_t::s_Resize );
		return p_struct;
	}
	
	UX_DECLARE_META_OBJECT( UXTypesExt::variant_array_t )
	{
		UXMetaTypes::CMetaVarArrayType *	p_var_array = new UXMetaTypes::CMetaVarArrayType( pName, uOffset );
		return p_var_array;
	}
	
	UXMetaTypes::IMetaBaseType * CreateMetaArray(uni_c_string pName, usize uOffset, UXMetaTypes::PResizeProc_t pProc, usize uSize, UXMetaTypes::IMetaBaseType *pType)
	{
		UXMetaTypes::CMetaArrayType *	p_arr = new UXMetaTypes::CMetaArrayType( pName, uOffset, uSize, pType );
		p_arr->SetProcs( pProc );
		return p_arr;
	}

//-------------------------------------------------------------------
	
}	// UX_STL